package com.zlfund.cat.demo;

import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
 * Created by chenj
 * Created on 2017/7/19
 */

public class WaveView extends View {
    private Context mContext;
    private Path mForeGroundPath, mBackgroundPath;
    private Paint mForeGroundPaint, mBackgroundPaint;
    private final static float mForeGroundStart = 0;
    private final static float mBackgroundStart = (float) (Math.PI / 2);
    private int mWidth,mHeight;
    private float mForeGroundWaveWidth,mBackGroundWaveWidth;       //显示几个完整周期
    private float mForeGroundAmplitude,mBackGroundAmplitude;       //振幅
    private float mForeGroundDWidth,mBackGroundDWidth;
    private ObjectAnimator mForeGroundObjAnim,mBackGroundObjAnim;
    private float mBaseLineHeight1,mBaseLineHeight2;  //振幅中心x轴所在高度
    private double mForeGroundParam;
    private double mBackGroundParam;

    public WaveView(Context context) {
        this(context,null);
    }

    public WaveView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        mForeGroundPath = new Path();
        mBackgroundPath = new Path();
        TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.WaveView);
        mForeGroundWaveWidth = a.getFloat(R.styleable.WaveView_foreground_wave_width,0.5f);
        mBackGroundWaveWidth = a.getFloat(R.styleable.WaveView_background_wave_width,0.7f);
        int foreGroundColor = a.getColor(R.styleable.WaveView_foreground_color, Color.GRAY);
        int backGroundColor = a.getColor(R.styleable.WaveView_background_color, Color.LTGRAY);
        mForeGroundAmplitude = a.getFloat(R.styleable.WaveView_foreground_amplitude,0.3f);
        mBackGroundAmplitude = a.getFloat(R.styleable.WaveView_background_amplitude,0.15f);
        mBaseLineHeight1 = a.getFloat(R.styleable.WaveView_wave_baseline1,0.5f);
        mBaseLineHeight2 = a.getFloat(R.styleable.WaveView_wave_baseline2,0.45f);
        a.recycle();
        mForeGroundPaint = getPaint(foreGroundColor);
        mBackgroundPaint = getPaint(backGroundColor);
        mForeGroundObjAnim = getObjAnim("ForeGroundDWidth",ValueAnimator.RESTART,Integer.MAX_VALUE,new LinearInterpolator(),3000,0.0f,(float) (2 * Math.PI));
        mBackGroundObjAnim = getObjAnim("BackGroundDWidth",ValueAnimator.RESTART,Integer.MAX_VALUE,new LinearInterpolator(),3500,0.0f,(float) (2 * Math.PI));
        mBackGroundObjAnim.start();
        mForeGroundObjAnim.start();
    }

    public ObjectAnimator getObjAnim(String propertyName, int repeatMode, int repeatCount, TimeInterpolator interpolator, int duration, float... vals){
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this,propertyName,vals);
        objectAnimator.setDuration(duration);
        objectAnimator.setRepeatMode(repeatMode);
        objectAnimator.setRepeatCount(repeatCount);
        objectAnimator.setInterpolator(interpolator);
        return objectAnimator;
    }

    public Paint getPaint(int color) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(color);
        return paint;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mWidth == 0){
            mWidth = getWidth();
            mHeight = getHeight();
            if (mWidth == 0) return;
            mForeGroundParam = 2 * mForeGroundWaveWidth * Math.PI / mWidth;
            mBackGroundParam = 2 * mBackGroundWaveWidth * Math.PI / mWidth;
        }

        mForeGroundPath.reset();
        mBackgroundPath.reset();
        mForeGroundPath.moveTo(0, getSinHeight(true,mForeGroundStart / mForeGroundParam + mForeGroundDWidth / mForeGroundParam));
        mBackgroundPath.moveTo(0, getSinHeight(false,mBackgroundStart / mBackGroundParam + mForeGroundDWidth / mBackGroundParam));
        int curWidth = 0;
        while (curWidth < mWidth){
            curWidth++;
            mForeGroundPath.lineTo(curWidth,getSinHeight(true,mForeGroundStart / mForeGroundParam + mForeGroundDWidth / mForeGroundParam - curWidth));
            mBackgroundPath.lineTo(curWidth, getSinHeight(false,mBackgroundStart / mBackGroundParam + mForeGroundDWidth / mBackGroundParam - curWidth));
        }
        mForeGroundPath.lineTo(mWidth,mHeight);
        mForeGroundPath.lineTo(0,mHeight);
        mForeGroundPath.close();
        mBackgroundPath.lineTo(mWidth,mHeight);
        mBackgroundPath.lineTo(0,mHeight);
        mBackgroundPath.close();
        canvas.drawPath(mBackgroundPath, mBackgroundPaint);
        canvas.saveLayerAlpha(0,0,mWidth,mHeight,0x77,Canvas.ALL_SAVE_FLAG);
        canvas.drawPath(mForeGroundPath, mForeGroundPaint);
        canvas.restore();

    }

    private float getSinHeight(boolean isForeGroundWave,double ang){
        if (isForeGroundWave)
            return mHeight * mBaseLineHeight1 - (float) (mHeight * mForeGroundAmplitude * Math.sin(ang * mForeGroundParam));
        else return mHeight * mBaseLineHeight2 - (float) (mHeight * mBackGroundAmplitude * Math.sin(ang * mBackGroundParam));
    }

    public float getForeGroundDWidth() {
        return mForeGroundDWidth;
    }

    public void setForeGroundDWidth(float foreGroundDWidth) {
        mForeGroundDWidth = foreGroundDWidth;
        postInvalidate();
    }

    public float getBackGroundDWidth() {
        return mBackGroundDWidth;
    }

    public void setBackGroundDWidth(float backGroundDWidth) {
        mBackGroundDWidth = backGroundDWidth;
        postInvalidate();
    }
}
